#include "xdatatest.h"
#include "xmppcore/jabberid.h"
#include "xmppcore/xmppparsingfactory.h"
#include "xmppcore/iq.h"
#include "xdata/xdataformparserfactory.h"

#include <QtTest/QTest>

namespace yoohoo_xdata {

Register::Register() : _dataForm(0) {
}

Register::~Register() {
	if (_dataForm) {
		delete _dataForm;
	}
}

XDataForm* Register::dataForm() {
	return _dataForm;
}

void Register::setDataForm(XDataForm* dataForm) {
	_dataForm = dataForm;
}

RegisterParser::RegisterParser() : _register(0) {
}

XmppObject* RegisterParser::obj() {
	return _register;
}

bool RegisterParser::processAttributes(QString path, QList<ParsingAttribute> attributes) {
	if ("query" != path || attributes.size() != 0) {
		return false;
	}

	_register = new Register;
	return true;
}

bool RegisterParser::processText(QString path, QString text) {
	if ("query" != path || !text.isEmpty()) {
		return false;
	}

	return true;
}

bool RegisterParser::processEmbeddedObject(ProtocolKey protocolKey, XmppObject* object) {
	_register->setDataForm(static_cast<XDataForm*>(object));
	return true;
}

ProtocolKey RegisterParserFactory::protocolKey() {
	return ProtocolKey("query", "jabber:iq:register");
}

XmppParser* RegisterParserFactory::createParser() {
	return new RegisterParser;
}

void XDataTest::init() {
	_parsingFactory = new PredefinedXmppParsingFactory;
	_parsingFactory->setDebug(true);
	
	_parsingFactory->registerParser(new RegisterParserFactory, ProtocolRelation(Iq::PROTOCOL_KEY, ProtocolKey("query", "jabber:iq:register")));
	_parsingFactory->registerParser(new XDataFormParserFactory, ProtocolRelation(ProtocolKey("query", "jabber:iq:register"), ProtocolKey("x", "jabber:x:data")));
}

void XDataTest::testParsing() {
	QString registrationFormXml =
	"<iq type='result' id='register_0' from='192.168.1.101' xml:lang='en_US'>"
		"<query xmlns='jabber:iq:register'>"
			"<x xmlns='jabber:x:data' type='form'>"
				"<title>Registration</title>"
				"<instructions>Please provide the following information to register for our service!</instructions>"
				"<field type='hidden' var='FORM_TYPE'>"
					"<value>jabber:iq:register</value>"
				"</field>"
				"<field type='text-single' label='User Name' var='username'>"
					"<required/>"
				"</field>"
				"<field type='text-private' label='Password' var='password'>"
					"<desc>Minimum 6 characters</desc>"
					"<required/>"
				"</field>"
				"<field type='text-private' label='Confirmed Password' var='confirmedpassword'>"
					"<required/>"
				"</field>"
				"<field type='text-single' label='Given Name' var='firstname'/>"
				"<field type='text-single' label='Family Name' var='lastname'/>"
				"<field type='list-single' label='Gender' var='x-gender'>"
					"<option label='Male'><value>M</value></option>"
					"<option label='Female'><value>F</value></option>"
				"</field>"
			"</x>"
		"</query>"
	"</iq>";

	XmppElement* element = _parsingFactory->parse(registrationFormXml);
	QVERIFY(element);

	Iq* iq = dynamic_cast<Iq*>(element);
	QVERIFY(iq);

	XmppObject* obj = iq->obj();
	QVERIFY(obj);

	Register* _register = dynamic_cast<Register*>(iq->obj());
	QVERIFY(_register);

	XDataForm* dataForm = _register->dataForm();

	QCOMPARE(QString("Registration"), dataForm->title());
	QCOMPARE(QString("Please provide the following information to register for our service!"), dataForm->instructions());

	QList<XDataField> fields = dataForm->fields();

	XDataField formType = fields.at(0);
	QCOMPARE(QString("FORM_TYPE"), formType.var());
	QVERIFY(formType.values().size() > 0);
	QCOMPARE(QString("jabber:iq:register"), formType.values()[0]);
	QCOMPARE(XDataField::HIDDEN, formType.type());

	XDataField userName = fields.at(1);
	QCOMPARE(XDataField::TEXT_SINGLE, userName.type());
	QCOMPARE(QString("username"), userName.var());
	QCOMPARE(QString("User Name"), userName.label());
	QVERIFY(userName.isRequired());

	XDataField password = fields.at(2);
	QCOMPARE(XDataField::TEXT_PRIVATE, password.type());
	QCOMPARE(QString("password"), password.var());
	QCOMPARE(QString("Password"), password.label());
	QCOMPARE(QString("Minimum 6 characters"), password.desc());
	QVERIFY(password.isRequired());

	XDataField confirmedPassword = fields.at(3);
	QCOMPARE(XDataField::TEXT_PRIVATE, confirmedPassword.type());
	QCOMPARE(QString("confirmedpassword"), confirmedPassword.var());
	QCOMPARE(QString("Confirmed Password"), confirmedPassword.label());
	QVERIFY(confirmedPassword.isRequired());

	XDataField givenName = fields.at(4);
	QCOMPARE(XDataField::TEXT_SINGLE, givenName.type());
	QCOMPARE(QString("firstname"), givenName.var());
	QCOMPARE(QString("Given Name"), givenName.label());
	QVERIFY(!givenName.isRequired());

	XDataField lastName = fields.at(5);
	QCOMPARE(XDataField::TEXT_SINGLE, lastName.type());
	QCOMPARE(QString("lastname"), lastName.var());
	QCOMPARE(QString("Family Name"), lastName.label());
	QVERIFY(!lastName.isRequired());

	XDataField xGender = fields.at(6);
	QCOMPARE(XDataField::LIST_SINGLE, xGender.type());
	QCOMPARE(QString("x-gender"), xGender.var());
	QCOMPARE(QString("Gender"), xGender.label());
	QList<XDataOption> options = xGender.options();
	QVERIFY(options.size() == 2);
	XDataOption male = options.at(0);
	QCOMPARE(QString("Male"), male.label());
	QCOMPARE(QString("M"), male.value());
	XDataOption female = options.at(1);
	QCOMPARE(QString("Female"), female.label());
	QCOMPARE(QString("F"), female.value());

	delete element;
}

void XDataTest::testTranslating() {
	QString submitXml =
		"<x xmlns='jabber:x:data' type='submit'>"
			"<field type='hidden' var='FORM_TYPE'>"
				"<value>jabber:iq:register</value>"
			"</field>"
			"<field type='text-single' label='Given Name' var='first'>"
				"<value>Juliet</value>"
			"</field>"
			"<field type='text-single' label='Family Name' var='last'>"
				"<value>Capulet</value></field>"
			"<field type='text-single' label='Email Address' var='email'>"
				"<value>juliet@capulet.com</value>"
			"</field>"
			"<field type='list-single' label='Gender' var='x-gender'>"
				"<value>F</value>"
			"</field>"
		"</x>";

	XDataForm submitForm;
	submitForm.setType(XDataForm::SUBMIT);

	XDataField formType(XDataField::HIDDEN);
	formType.setVar("FORM_TYPE");
	formType.values().append("jabber:iq:register");
	submitForm.fields().push_back(formType);

	XDataField first(XDataField::TEXT_SINGLE);
	first.setVar("first");
	first.setLabel("Given Name");
	first.values().append("Juliet");
	submitForm.fields().push_back(first);

	XDataField last(XDataField::TEXT_SINGLE);
	last.setVar("last");
	last.setLabel("Family Name");
	last.values().append("Capulet");
	submitForm.fields().push_back(last);

	XDataField email(XDataField::TEXT_SINGLE);
	email.setVar("email");
	email.setLabel("Email Address");
	email.values().append("juliet@capulet.com");
	submitForm.fields().push_back(email);

	XDataField xGender(XDataField::LIST_SINGLE);
	xGender.setVar("x-gender");
	xGender.setLabel("Gender");
	xGender.values().append("F");
	submitForm.fields().push_back(xGender);

	QCOMPARE(submitForm.toXml(), submitXml);
}

void XDataTest::cleanup() {
	delete _parsingFactory;
}

}

QTEST_MAIN(yoohoo_xdata::XDataTest);
